﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;

using Noris.Tools.TraceVisualiser.Support;

namespace Noris.Tools.TraceVisualiser.Components
{
    internal class DColGrid : DblGraphControl, IHeaderSync
    {
        #region KONSTRUKCE
        public DColGrid()
        {
            Size size = this.ClientSize;
            this.Header = new DColumns() { Bounds = new Rectangle(0, 0, size.Width, 30) };
            this.Grid = new GridGraphCls() { Bounds = new Rectangle(0, 30, size.Width, size.Height - 30) };

            // Spojení objektů (Header řídí, Grid čte):
            this.Grid.Columns = this.Header;
            this.Grid.TimeAxisCalc = this.Header.TimeAxisCalc;                     // Spojí časovou kalkulačku grafu s časovou kalkulačkou hlavičky

            this.Controls.Add(this.Header);
            this.Controls.Add(this.Grid);
            this._RegisterEventsInternal();
            this._RegisterEventsHeader();
            this._RegisterEventsGrid();
        }
        internal DColumns Header { get; private set; }
        internal GridGraphCls Grid { get; private set; }
        /// <summary>
        /// Disposable
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (this.Header != null)
                this.Header.Dispose();
            if (this.Grid != null)
                this.Grid.Dispose();
            base.Dispose(disposing);
        }
        #endregion
        #region SPOLEČNÉ PROPERTY, EVENTY, METODY
        /// <summary>
        /// Draw tohoto prvku vyvolá Draw pro Header i Grid
        /// </summary>
        /// <param name="drawRectangle"></param>
        public override void Draw(Rectangle drawRectangle)
        {
            this.Header.Draw();
            this.Grid.Draw();
        }
        /// <summary>
        /// Potlačení kreslení při provádění rozsáhlejších změn. Po ukončení je třeba nastavit na false !
        /// Default = false = kreslení není potlačeno.
        /// Při provádění rozsáhlejších změn je vhodné nastavit na true, a po dokončení změn vrátit na false => tím se automaticky vyvolá Draw.
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override bool SuppressDrawing
        {
            get { return base.SuppressDrawing; }
            set
            {
                base.SuppressDrawing = value;
                this.Header.SuppressDrawing = value;
                this.Grid.SuppressDrawing = value;
            }
        }
        /// <summary>
        /// Umožní řídit potlačení vykreslování v hierarchii metod.
        /// Zajistí, že vykreslování bude potlačeno přinejmenším do párového vyvolání metody SuppressDrawingPop().
        /// Chování je obdobou chování Stacku: první Push zablokuje kreslení, následné Push a Pop to nezmění, poslední Pop to povolí.
        /// Podmínka: Push a Pop musí být v páru, jinak kreslení zamrzne.
        /// Řešení: je možno kdykoliv vložit SuppressDrawing = false a vykreslování ožije (nepárový zásobník se vynuluje).
        /// </summary>
        public override void SuppressDrawingPush()
        {
            base.SuppressDrawingPush();
            this.Header.SuppressDrawingPush();
            this.Grid.SuppressDrawingPush();
        }
        /// <summary>
        /// Umožní řídit potlačení vykreslování v hierarchii metod.
        /// Zajistí, že vykreslování bude potlačeno přinejmenším do párového vyvolání metody SuppressDrawingPop().
        /// Chování je obdobou chování Stacku: první Push zablokuje kreslení, následné Push & Pop to nezmění, poslední Pop to povolí.
        /// Podmínka: Push a Pop musí být v páru, jinak kreslení zamrzne.
        /// Řešení: je možno kdykoliv vložit SuppressDrawing = false a vykreslování ožije (nepárový zásobník se vynuluje).
        /// </summary>
        public override void SuppressDrawingPop()
        {
            base.SuppressDrawingPop();
            this.Header.SuppressDrawingPop();
            this.Grid.SuppressDrawingPop();
        }
        /// <summary>
        /// Graf má nyní určené svoje Bounds, má platné hodnoty v Header.Heights a ColumnWidths.
        /// Měl by nyní provést ArrangeComponents a přenést ColumnWidths z Headeru do Gridu.
        /// </summary>
        internal void LayoutAccept()
        {
            this._ArrangeComponents();
            this.Grid.AcceptColumnDimensions();
        }
        #endregion
        #region ŘÍZENÍ RESIZE VNITŘNÍCH OBJEKTŮ
        protected override void OnSizeChanged(EventArgs e)
        {
            try
            {
                this._ResizeInProgress = true;                     // Zablokuje výkon v handleru this._AfterTimeAxisChange()
				this._ArrangeComponents();

                // Nyní proběhne resize rozměrů komponent (grafy: skrz splittery), ale jejich Draw se neprovede, je SuppressDrawing:
                base.OnSizeChanged(e);                             // zde se vyvolá this.OnResize(), a také OnResize všech podřízených.

            }
            finally
            {
                this._ResizeInProgress = false;
            }
        }
		/// <summary>
		/// Uspořádá vnitřní objekty tak, aby korektně vyplnily prostor this
		/// </summary>
		private void _ArrangeComponents()
		{
			_ArrangeComponents(this.Header.ColumnHeaderHeightInteractive);
		}
		/// <summary>
		/// Uspořádá vnitřní objekty tak, aby korektně vyplnily prostor this
		/// </summary>
		private void _ArrangeComponents(int headerHeight)
		{
			Size size = this.ClientSize;

			if (this.Header.Width != size.Width)
				this.Header.Width = size.Width;

			int y = this.Header.Top + headerHeight;
			Rectangle bounds = new Rectangle(0, y, size.Width, size.Height - y);
			if (this.Grid.Bounds != bounds)
				this.Grid.Bounds = bounds;
		}
        private bool _ResizeInProgress = false;
        #endregion
        #region INTERNÍ EVENTHANDLERY
        /// <summary>
        /// Registrace interních handlerů
        /// </summary>
        private void _RegisterEventsInternal()
        {
            this.GotFocus += new EventHandler(DColGrid_GotFocus);
        }
        /// <summary>
        /// Je vyvoláno poté, kdy objekt DColGrid dostane focus.
        /// Protože jde o Control, focus dostat může - ale musí jej předat do grafu.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DColGrid_GotFocus(object sender, EventArgs e)
        {
            this.Grid.Focus();
        }
        /// <summary>
        /// Handler události, kdy se v Headeru změnil řádkový filtr.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnRowFilterChanged(object sender, DColumnRowFilterEventArgs args)
        {
            this.Grid.AcceptRowFilter(args.RowFilter);
        }
        /// <summary>
        /// Handler události, kdy se v Headeru změnilo třídění dat.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnColumnSortChanged(object sender, DColumnEventArgs args)
        {
        }
        /// <summary>
        /// Handler události, kdy se v Headeru změnila časová osa
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnTimeAxisChange(object sender, TimeAxisChangeEventArgs args)
        {
            this.Grid.Draw();
        }
        /// <summary>
        /// Handler události, kdy se v Headeru interaktivně mění jeho výška.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnColumnHeaderHeightChanging(object sender, EventArgs args)
        {
			this._ArrangeComponents(this.Header.ColumnHeaderHeightInteractive);
        }
        /// <summary>
        /// Handler události, kdy se v Headeru změnila jeho výška (dokončení interaktivní změny, nebo provedení neinteraktivní změny).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnColumnHeaderHeightChanged(object sender, EventArgs args)
        {
			this._ArrangeComponents(this.Header.ColumnHeaderHeight);
		}
        /// <summary>
        /// Handler události, kdy došlo k jakékoli změně sloupců v Headeru a je třeba ji promítnout do Gridu
        /// </summary>
        private void _OnColumnsChanged()
        {
            this.Grid.AcceptColumnDimensions();
        }
        /// <summary>
        /// Handler události, kdy se v Headeru mění interaktivně šířka sloupců, změna stále probíhá.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnColumnWidthChanging(object sender, DColumnWidthEventArgs args)
        {
            this.Grid.AcceptColumnDimensions();
        }
        /// <summary>
        /// Handler události, kdy se v Headeru změnila šířka sloupců (dokončení interaktivní změny, nebo provedení neinteraktivní změny).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _OnColumnWidthChanged(object sender, DColumnWidthEventArgs args)
        {
            this.Grid.AcceptColumnDimensions();
        }
		public override void Refresh()
		{
			if (this.Header != null) this.Header.Refresh();
			if (this.Grid != null) this.Grid.Refresh();
			base.Refresh();
		}
		#endregion
        #region MŮSTEK NA HEADER - PROPERTY, EVENTY, METODY
        #region property
        /// <summary>
        /// Pozice Top záhlaví sloupců interaktivní (mění se v průběhu vertical move)
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Pozice Top záhlaví sloupců interaktivní (mění se v průběhu vertical move)")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ColumnHeaderTopInteractive
        {
            get { return this.Header.ColumnHeaderTopInteractive; }
            set { this.Header.ColumnHeaderTopInteractive = value; }
        }
        /// <summary>
        /// Pozice Top záhlaví sloupců aktuální (trvalá, při pohybu je zde původní pozice před zahájením pohybu)
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Pozice Top záhlaví sloupců aktuální (trvalá, při pohybu je zde původní pozice před zahájením pohybu)")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ColumnHeaderTop
        {
            get { return this.Header.ColumnHeaderTop; }
            set { this.Header.ColumnHeaderTop = value; }
        }
        /// <summary>
        /// Výška záhlaví sloupců interaktivní (mění se v průběhu resize)
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Výška záhlaví sloupců interaktivní (mění se v průběhu resize)")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ColumnHeaderHeightInteractive
        {
            get { return this.Header.ColumnHeaderHeightInteractive; }
            set { this.Header.ColumnHeaderHeightInteractive = value; }
        }
        /// <summary>
        /// Výška záhlaví sloupců aktuální (trvalá, při resizování je zde výška před zahájením resize)
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Výška záhlaví sloupců aktuální (trvalá, při resizování je zde výška před zahájením resize)")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ColumnHeaderHeight
        {
            get { return this.Header.ColumnHeaderHeight; }
            set { this.Header.ColumnHeaderHeight = value; }
        }
        /// <summary>
        /// Nejmenší povolená výška ColumnHeader
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Nejmenší povolená výška ColumnHeader")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int? ColumnHeaderHeightMinimum
        {
            get { return this.Header.ColumnHeaderHeightMinimum; }
            set { this.Header.ColumnHeaderHeightMinimum = value; }
        }
        /// <summary>
        /// Největší povolená výška ColumnHeader
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Největší povolená výška ColumnHeader")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int? ColumnHeaderHeightMaximum
        {
            get { return this.Header.ColumnHeaderHeightMaximum; }
            set { this.Header.ColumnHeaderHeightMaximum = value; }
        }
        /// <summary>
        /// Horní limit pro hodnotu Top. Pokud je null, není omezeno. Nemůže být záporný.
        /// Pokud by se uživatel snažil posunout objekt na pozici Top menší (nahoru), než je tento limit, pak objekt zůstane na tomto limitu.
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Horní limit pro hodnotu Top")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int? ColumnHeaderTopUpperLimit
        {
            get { return this.Header.ColumnHeaderTopUpperLimit; }
            set { this.Header.ColumnHeaderTopUpperLimit = value; }
        }
        /// <summary>
        /// Dolní limit pro hodnotu Top. Pokud je null, není omezeno. Může být záporný, pak se počítá od souřadnic Bottom (Parent i this)
        /// Pokud by se uživatel snažil posunout objekt na pozici Top vyšší (nahoru), než je tento limit, pak objekt zůstane na tomto limitu.
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Dolní limit pro hodnotu Top")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int? ColumnHeaderTopDownLimit
        {
            get { return this.Header.ColumnHeaderTopDownLimit; }
            set { this.Header.ColumnHeaderTopDownLimit = value; }
        }
        /// <summary>
        /// Je možno interaktivně měnit výšku ColumnHeaderHeight?
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Je možno interaktivně měnit výšku ColumnHeaderHeight?")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public bool ColumnHeaderHeightSizable
        {
            get { return this.Header.ColumnHeaderHeightSizable; }
            set { this.Header.ColumnHeaderHeightSizable = value; }
        }
        /// <summary>
        /// Režim, ve kterém se pohybuje hlavička a její parent
        /// </summary>
        [Browsable(true)]
        [Category("DColumns")]
        [Description("Režim, ve kterém se pohybuje hlavička a její parent")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public DColumnsHeaderMoveMode ColumnHeaderMoveMode
        {
            get { return this.Header.ColumnHeaderMoveMode; }
            set { this.Header.ColumnHeaderMoveMode = value; }
        }
        /// <summary>
        /// Počet sloupců
        /// </summary>
        public int ColumnsCount
        {
            get { return this.Header.ColumnsCount; }
        }
        #endregion
        #region eventy
        /// <summary>
        /// Event, který bude vyvolán po změně hodnoty Text konkrétního sloupce
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po změně hodnoty Text konkrétního sloupce")]
        public event DColumnEventHandler ColumnTextChanged;
		/// <summary>
		/// Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny pozice Parent.Top + Parent.Height
		/// </summary>
		[Browsable(true)]
		[Category("Action")]
		[Description("Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny pozice Parent.Top + Parent.Height")]
		public event EventHandler ColumnHeaderParentTopMoving;
		/// <summary>
		/// Event, který bude vyvolán po dokončení interaktivní změny a pro provedení neinteraktivní změny pozice Parent.Top + Parent.Height"
		/// </summary>
		[Browsable(true)]
		[Category("Action")]
		[Description("Event, který bude vyvolán po dokončení interaktivní změny a pro provedení neinteraktivní změny pozice Parent.Top + Parent.Height")]
		public event EventHandler ColumnHeaderParentTopMoved;
        /// <summary>
        /// Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny pozice Top
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny pozice Top")]
        public event EventHandler ColumnHeaderTopChanging;
        /// <summary>
        /// Event, který bude vyvolán po dokončení interaktivní (výhradně !) změny pozice Top
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po dokončení interaktivní (výhradně !) změny a při každé neinteraktivní změně pozice Top")]
        public event EventHandler ColumnHeaderTopChanged;
		/// <summary>
		/// Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny výšky záhlaví
		/// </summary>
		[Browsable(true)]
		[Category("Action")]
		[Description("Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny výšky záhlaví")]
		public event EventHandler ColumnHeaderHeightChanging;
		/// <summary>
		/// Event, který bude vyvolán po dokončení interaktivní (výhradně !) změny výšky záhlaví
		/// </summary>
		[Browsable(true)]
		[Category("Action")]
        [Description("Event, který bude vyvolán po dokončení interaktivní (výhradně !) změny a při každé neinteraktivní změně výšky záhlaví")]
		public event EventHandler ColumnHeaderHeightChanged;
		/// <summary>
        /// Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny šířky konkrétního sloupce
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán opakovaně v průběhu interaktivní (výhradně !) změny šířky některého sloupce")]
        public event DColumnWidthEventHandler ColumnWidthChanging;
        /// <summary>
        /// Event, který bude vyvolán po dokončení interaktivní (výhradně !) změny šířky konkrétního sloupce
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po změně šířky některého sloupce")]
        public event DColumnWidthEventHandler ColumnWidthChanged;
        /// <summary>
        /// Event, který bude vyvolán po změně pořadí sloupce (a přepočtu pořadí ostatních sloupců)
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po změně pořadí sloupce (a přepočtu pořadí ostatních sloupců)")]
        public event DColumnEventHandler ColumnOrderChanged;
        /// <summary>
        /// Event, který bude vyvolán po změně režimu zobrazování hlavičky (HeaderMode) konkrétního sloupce
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po změně režimu zobrazování hlavičky (HeaderMode) konkrétního sloupce")]
        public event DColumnEventHandler ColumnHeaderModeChanged;
        /// <summary>
        /// Event, který bude vyvolán po změně hodnoty Visible konkrétního sloupce
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po změně hodnoty Visible konkrétního sloupce")]
        public event DColumnEventHandler ColumnVisibleChanged;
        /// <summary>
        /// Event, který bude vyvolán po jakékoli změně počtu sloupců (Add, Remove, Clear)
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po jakékoli změně počtu sloupců (Add, Remove, Clear)")]
        public event EventHandler ColumnCountChanged;
        /// <summary>
        /// Event, který bude vyvolán po jakékoli změně v řádkovém filtru
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po jakékoli změně v řádkovém filtru")]
        public event DColumnRowFilterEventHandler RowFilterChanged;
        /// <summary>
        /// Event, který bude vyvolán po změně třídění na některém sloupci
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán po změně třídění na některém sloupci")]
        public event DColumnEventHandler ColumnSortChanged;
        /// <summary>
        /// Event, který bude vyvolán při změnách zobrazeného času na časové ose
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který bude vyvolán při změnách zobrazeného času na časové ose")]
        public event TimeAxisChangeHandler TimeAxisChange;
        #endregion
        #region metody
        /// <summary>
        /// Vymaže všechny columny.
        /// </summary>
        public void ColumnsClear()
        {
            this.Header.ColumnsClear();
        }
        /// <summary>
        /// Přidá sloupec.
        /// Vrátí jej (lze tak nastavit jeho další vlastnosti).
        /// </summary>
        /// <param name="text">Text v záhlaví sloupci</param>
        /// <returns></returns>
        public DColumn ColumnAdd(string text)
        {
            return this.Header.ColumnAdd(text);
        }
        /// <summary>
        /// Přidá sloupec.
        /// Vrátí jej (lze tak nastavit jeho další vlastnosti).
        /// </summary>
        /// <param name="text">Text v záhlaví sloupci</param>
        /// <param name="key">Název sloupce, pod nímž jej lze vyhledat</param>
        /// <returns></returns>
        public DColumn ColumnAdd(string text, string key)
        {
            return this.Header.ColumnAdd(text, key);
        }
        /// <summary>
        /// Přidá sloupec.
        /// Vrátí jej (lze tak nastavit jeho další vlastnosti).
        /// </summary>
        /// <param name="text">Text v záhlaví sloupci</param>
        /// <param name="width">Šířka sloupce</param>
        /// <returns></returns>
        public DColumn ColumnAdd(string text, int width)
        {
            return this.Header.ColumnAdd(text, width);
        }
        /// <summary>
        /// Přidá sloupec.
        /// Vrátí jej (lze tak nastavit jeho další vlastnosti).
        /// </summary>
        /// <param name="text">Text v záhlaví sloupci</param>
        /// <param name="key">Název sloupce, pod nímž jej lze vyhledat</param>
        /// <param name="width">Šířka sloupce</param>
        /// <returns></returns>
        public DColumn ColumnAdd(string text, string key, int width)
        {
            return this.Header.ColumnAdd(text, key, width);
        }
        /// <summary>
        /// Najde a vrátí sloupec podle jeho názvu.
        /// Pokud nenajde, vrátí null.
        /// </summary>
        /// <param name="key">Název sloupce, pod nímž jej lze vyhledat</param>
        /// <returns></returns>
        public DColumn ColumnGet(string key)
        {
            return this.Header.ColumnGet(key);
        }
        /// <summary>
        /// Najde a vrátí sloupec podle jeho logického indexu.
        /// Pokud nenajde, vrátí null.
        /// </summary>
        /// <param name="index">Index sloupce</param>
        /// <returns></returns>
        public DColumn ColumnGet(int index)
        {
            return this.Header.ColumnGet(index);
        }
        /// <summary>
        /// Najde index sloupce podle jeho názvu.
        /// </summary>
        /// <param name="key">Název sloupce, pod nímž jej lze vyhledat</param>
        /// <returns></returns>
        public int ColumnFindIndex(string key)
        {
            return this.Header.ColumnFindIndex(key);
        }
        /// <summary>
        /// Najde index daného sloupce.
        /// </summary>
        /// <param name="key">Název sloupce, pod nímž jej lze vyhledat</param>
        /// <returns></returns>
        public int ColumnFindIndex(DColumn column)
        {
            return this.Header.ColumnFindIndex(column);
        }
        /// <summary>
        /// Odebere sloupec podle jeho názvu.
        /// Pokud jej nenajde, nic nedělá.
        /// </summary>
        /// <param name="key">Název sloupce, pod nímž jej lze vyhledat</param>
        /// <returns></returns>
        public void ColumnRemove(string key)
        {
            this.Header.ColumnRemove(key);
        }
        /// <summary>
        /// Odebere sloupec podle jeho indexu.
        /// Pokud jej nenajde, nic nedělá.
        /// </summary>
        /// <param name="index">Index sloupce</param>
        /// <returns></returns>
        public void ColumnRemove(int index)
        {
            this.Header.ColumnRemove(index);
        }
        /// <summary>
        /// Odebere daný sloupec.
        /// Pokud jej nenajde, nic nedělá.
        /// </summary>
        /// <param name="column">Sloupec</param>
        /// <returns></returns>
        public void ColumnRemove(DColumn column)
        {
            this.Header.ColumnRemove(column);
        }
        /// <summary>
        /// Vrátí soupis columns, které jsou viditelné, v pořadí ve kterém mají být zobrazeny
        /// </summary>
        /// <returns></returns>
        public List<DColumn> GetVisibleColumns()
        {
            return this.Header.GetVisibleColumns();
        }
        /// <summary>
        /// Vrátí soupis columns, které jsou viditelné, v pořadí ve kterém mají být zobrazeny.
        /// Lze zvolit, zda jako první sloupec bude vrácen systémový sloupec (headers).
        /// </summary>
        /// <param name="withSysHeader">true = včetně systémového headeru (ten má příznak IsSystem = true, a Index = -1)</param>
        /// <returns></returns>
        internal List<DColumn> GetVisibleColumns(bool withSysHeader)
        {
            return this.Header.GetVisibleColumns(withSysHeader);
        }
        /// <summary>
        /// Vrátí soupis všech columns, nehledě na viditelné / neviditelné a na systémové, prostě všechny.
        /// Mohou být setříděné, podle parametru sorted.
        /// </summary>
        /// <param name="sorted">Požadavek na setřídění seznamu podle pořadí Order (false = budou v nativním pořadí dle indexu).</param>
        /// <returns></returns>
        internal List<DColumn> GetAllColumns(bool sorted)
        {
            return this.Header.GetAllColumns(sorted);
        }
        /// <summary>
        /// Nuluje řádkový filtr
        /// </summary>
        internal void RowFilterClear()
        {
            this.Header.RowFilterClear();
        }
        #endregion
        #endregion
        #region HEADER - EVENTHANLDERY
        private void _RegisterEventsHeader()
        {
            this.Header.ColumnTextChanged += new DColumnEventHandler(Header_ColumnTextChanged);
			this.Header.ColumnHeaderParentTopMoving += new EventHandler(Header_ColumnHeaderParentTopMoving);
			this.Header.ColumnHeaderParentTopMoved += new EventHandler(Header_ColumnHeaderParentTopMoved);
            this.Header.ColumnHeaderTopChanging += new EventHandler(Header_ColumnHeaderTopChanging);
            this.Header.ColumnHeaderTopChanged += new EventHandler(Header_ColumnHeaderTopChanged);
            this.Header.ColumnHeaderHeightChanging += new EventHandler(Header_ColumnHeaderHeightChanging);
            this.Header.ColumnHeaderHeightChanged += new EventHandler(Header_ColumnHeaderHeightChanged);
            this.Header.ColumnWidthChanging += new DColumnWidthEventHandler(Header_ColumnWidthChanging);
            this.Header.ColumnWidthChanged += new DColumnWidthEventHandler(Header_ColumnWidthChanged);
            this.Header.ColumnOrderChanged += new DColumnEventHandler(Header_ColumnOrderChanged);
            this.Header.ColumnHeaderModeChanged += new DColumnEventHandler(Header_ColumnHeaderModeChanged);
            this.Header.ColumnVisibleChanged += new DColumnEventHandler(Header_ColumnVisibleChanged);
            this.Header.ColumnCountChanged += new EventHandler(Header_ColumnCountChanged);
            this.Header.RowFilterChanged += new DColumnRowFilterEventHandler(Header_RowFilterChanged);
            this.Header.ColumnSortChanged += new DColumnEventHandler(Header_ColumnSortChanged);
            this.Header.TimeAxisChange += new TimeAxisChangeHandler(Header_TimeAxisChange);
        }
		// Předávání eventů z Header do handlerů navázaných na this:
        void Header_ColumnTextChanged(object sender, DColumnEventArgs args)
        {
            if (ColumnTextChanged != null) ColumnTextChanged(this, args);
        }
		void Header_ColumnHeaderParentTopMoving(object sender, EventArgs args)
		{
			if (ColumnHeaderParentTopMoving != null) ColumnHeaderParentTopMoving(this, args);
		}
		void Header_ColumnHeaderParentTopMoved(object sender, EventArgs args)
		{
			if (ColumnHeaderParentTopMoved != null) ColumnHeaderParentTopMoved(this, args);
		}
		void Header_ColumnHeaderTopChanging(object sender, EventArgs args)
        {
            if (ColumnHeaderTopChanging != null) ColumnHeaderTopChanging(this, args);
        }
        void Header_ColumnHeaderTopChanged(object sender, EventArgs args)
        {
            if (ColumnHeaderTopChanged != null) ColumnHeaderTopChanged(this, args);
        }
        void Header_ColumnHeaderHeightChanging(object sender, EventArgs args)
        {
            this._OnColumnHeaderHeightChanging(sender, args);
            if (ColumnHeaderHeightChanging != null) ColumnHeaderHeightChanging(this, args);
        }
        void Header_ColumnHeaderHeightChanged(object sender, EventArgs args)
        {
            this._OnColumnHeaderHeightChanged(sender, args);
            if (ColumnHeaderHeightChanged != null) ColumnHeaderHeightChanged(this, args);
        }
        void Header_ColumnWidthChanging(object sender, DColumnWidthEventArgs args)
        {
            this._OnColumnWidthChanging(sender, args);
            if (ColumnWidthChanging != null) ColumnWidthChanging(this, args);
        }
        void Header_ColumnWidthChanged(object sender, DColumnWidthEventArgs args)
        {
            this._OnColumnWidthChanged(sender, args);
            if (ColumnWidthChanged != null) ColumnWidthChanged(this, args);
        }
        void Header_ColumnOrderChanged(object sender, DColumnEventArgs args)
        {
            if (ColumnOrderChanged != null) ColumnOrderChanged(this, args);
        }
        void Header_ColumnHeaderModeChanged(object sender, DColumnEventArgs args)
        {
            if (ColumnHeaderModeChanged != null) ColumnHeaderModeChanged(this, args);
        }
        void Header_ColumnVisibleChanged(object sender, DColumnEventArgs args)
        {
            if (ColumnVisibleChanged != null) ColumnVisibleChanged(this, args);
        }
        void Header_ColumnCountChanged(object sender, EventArgs args)
        {
            if (ColumnCountChanged != null) ColumnCountChanged(this, args);
        }
        void Header_RowFilterChanged(object sender, DColumnRowFilterEventArgs args)
        {
            this._OnRowFilterChanged(sender, args);
            if (RowFilterChanged != null) RowFilterChanged(this, args);
        }
        void Header_ColumnSortChanged(object sender, DColumnEventArgs args)
        {
            this._OnColumnSortChanged(sender, args);
            if (ColumnSortChanged != null) ColumnSortChanged(this, args);
        }
        void Header_TimeAxisChange(object sender, TimeAxisChangeEventArgs args)
        {
            this._OnTimeAxisChange(sender, args);
            if (TimeAxisChange != null) TimeAxisChange(this, args);
        }
        #endregion
        #region MŮSTEK NA GRAF - PROPERTY, EVENTY, METODY
        #region property
        /// <summary>
        /// Deklarace tohoto grafu, jak jej deklaroval jeho deklarant
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public GraphDeclarationCls GraphDeclarationData
        {
            get { return this.Grid.GraphDeclarationData; }
            set
			{
				this.Grid.GraphDeclarationData = value;          // Grid se naváže na datový zdroj a napojí se na vlastnosti grafu
				this.Header.GraphDeclarationData = value;        // Headers si převezme sloupce
				this.Grid.RegisterDataSource(value.DataSource);  // Navážu se na datový zdroj
			}
        }
        /// <summary>
        /// Tag předaný v deklaraci tohoto grafu.
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new object Tag
        {
            get { return this.Grid.Tag; }
        }
        /// <summary>
        /// Výchozí typ grafu. Při tvorbě řádků bude datový zdroj požádán o tento typ grafu.
        /// Pokud bude moci vyhovět, vyhoví. Pokud ne, použije jiný vhodný typ grafu.
        /// Skutečně vykreslený typ grafu je dán tím, jaký typ grafu akceptuje datový zdroj pro aktuální typ dat.
        /// </summary>
        [Description("Výchozí typ grafu. Při tvorbě řádků bude datový zdroj požádán o tento typ grafu.")]
        [Category("Vzhled")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public RowGraphMode DefaultGraphType
        {
            get { return this.Grid.DefaultGraphType; }
            set { this.Grid.DefaultGraphType = value; }
        }
        /// <summary>
        /// ID grafu. Pokud je více grafů napojeno na jeden datový zdroj, a pokud zdroj pracuje asynchronně, 
        /// pak vyřizuje požadavky z více grafů.
        /// Pak musí každý graf znát své ID při sestavování požadavků na data, 
        /// a zvenku musí být známo jeho ID při určování grafu, jehož požadavek byl asynchronně vyřízen, a jemuž se předává výsledek.
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public int GraphID
        {
            get { return this.Grid.GraphID; }
            set { this.Grid.GraphID = value; }
        }
        /// <summary>
        /// Barva pozadí mimo řádky (dole pod posledním řádkem)
        /// </summary>
        [Description("Barva pozadí mimo řádky (dole pod posledním řádkem)")]
        [Category("Vzhled")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override Color BackColor
        {
            get { return this.Grid.BackColor; }
            set { this.Grid.BackColor = value; }
        }
        /// <summary>
        /// Barva pozadí řádků (buňky)
        /// </summary>
        [Description("Barva pozadí řádků (buňky)")]
        [Category("Vzhled")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Color CellBackColor
        {
            get { return this.Grid.CellBackColor; }
            set { this.Grid.CellBackColor = value; }
        }
        /// <summary>
        /// { get; set; } Aktuálně viditelný časový rozsah. Změna způsobí přenačtení a nové zobrazení grafu.
        /// </summary>
        [Description("Aktuálně viditelný časový rozsah. Změna způsobí přenačtení a nové zobrazení grafu.")]
        [Category("Vzhled")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public TimeRange CurrentTimeRange
        {
            get { return this.Grid.CurrentTimeRange; }
            set { this.Header.SetTimeAxisData(new TimeAxisSetAxisArgs(value)); }
        }
        /// <summary>
        /// { get; } Obsahuje informaci o tom, zda se právě provádí Zooming.
        /// Na to by měla reagovat ikona Zoomu, typicky CheckBox: Checked = IsInZoomingMode;
        /// Změna hodnoty vyvolává event EditorStateChanged.
        /// </summary>
        [Category("Data")]
        [Description("Obsahuje informaci o tom, zda se právě provádí zoomování. Pokud je true, měl by ToolButton být zobrazen jako Checked. Změna hodnoty vyvolává event EditorStateChanged.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsInZoomingMode
        {
            get { return this.Grid.IsInDesignMode; }
        }
        /// <summary>
        /// { get; set; } Obsahuje / nastavuje informaci o tom, zda graf je právě ve stavu SnapToGrid.
        /// Změna hodnoty (set) nevyvolá žádnou přímou akci (ani nevyvolá EditorStateChanged), protože tam odsud je typicky voláno!
        /// Hodnota se uplatní v průběhu interaktivního přesunu elementů.
        /// </summary>
        [Category("Data")]
        [Description("Obsahuje / nastavuje informaci o tom, zda graf je právě ve stavu SnapToGrid.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool SnapToGrid
        {
            get { return this.Grid.SnapToGrid; }
            set { this.Grid.SnapToGrid = value; }
        }
        /// <summary> { get; }
        /// Objekt, který obsahuje metody použitelné pro přepočty vizuálních a časových dat na časové ose (datum - pixel).
        /// Jde o referenci na objekt časové osy, která interně implementuje objekt časové kalkulačky i pro své účely.
        /// Poskytuje přístup k tomuto objektu přes interface ITimeAxisCalc, přes které lze přepočítávat souřadnice.
        /// </summary>
        internal ITimeAxisCalc TimeAxisCalc
        {
            get { return this.Grid.TimeAxisCalc; }
        }
        /// <summary>
        /// Obsahuje příznak (true), zda již došlo k prvotnímu načtení dat (metodou ReadFirstDataList()).
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool FirstDataLoaded
        {
            get { return this.Grid.FirstDataLoaded; }
        }
        /// <summary>
        /// Obsahuje GID dat, která se automaticky načtou před prvním zobrazením grafu.
        /// Vložit hodnotu je možno pouze před tím, než dojde k prvnímu načtení dat (dokud je DataFirstLoaded == false).
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public GID FirstGIdToLoad
        {
            get { return this.Grid.FirstGIdToLoad; }
            set { this.Grid.FirstGIdToLoad = value; }
        }
        /// <summary>
        /// Povoluje použití interního tooltipu. Default je true. Je vhodné zakázat, pokud se informace o tooltipu přebírá přes event ToolTipChanged.
        /// </summary>
        [Browsable(false)]
        [Category("Data")]
        [Description("Povoluje použití interního tooltipu. Default je true. Je vhodné zakázat, pokud se informace o tooltipu přebírá přes event ToolTipChanged.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool ToolTipEnabled { get { return this.Grid.ToolTipEnabled; } set { this.Grid.ToolTipEnabled = value; } }
        /// <summary>
        /// Nastavuje dobu svícení tooltipu před tím, než samovolně zhasne. V milisekundách. Default = 10000.
        /// </summary>
        [Browsable(false)]
        [Category("Data")]
        [Description("Nastavuje dobu svícení tooltipu před tím, než samovolně zhasne. V milisekundách. Default = 10000.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ToolTipDuration { get { return this.Grid.ToolTipDuration; } set { this.Grid.ToolTipDuration = value; } }
        #endregion
        #region eventy
        /// <summary>
        /// Event, kterým si třída GridGraphCls žádá o nastavení časového měřítka osy.
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, kterým si třída GridGraphCls žádá o nastavení časového měřítka osy")]
        public event TimeAxisSetAxisHandler StoreTimeAxisData;
        /// <summary>
        /// Event vyvolaný v situaci, kdy tento graf (typicky vlivem interaktivní funkce) požaduje reload všech dat na všech grafech.
        /// Tento event typicky obsluhuje multiplexor a řízení přechází do metody .
        /// </summary>
        [Description("Event vyvolaný v situaci, kdy tento graf (typicky vlivem interaktivní funkce) požaduje reload všech dat na všech grafech.")]
        [Category("Action")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Browsable(true)]
        public event GridGraphEventHandler RequestReloadAllRows;
        /// <summary>
        /// Event vyvolaný po aktivaci grafického elementu, poté kdy jsou rozsvíceny vztahy tohoto elementu.
        /// Umožní se tak, aby vedlejší graf rozsvítil odpovídající záznamy.
        /// </summary>
        [Description("Event vyvolaný po aktivaci grafického elementu, poté kdy jsou rozsvíceny vztahy tohoto elementu.")]
        [Category("Action")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Browsable(true)]
        public event GridGraphEventHandler GraphElementClick;
        /// <summary>
        /// Event vyvolaný po doubleclicku na některém grafu.
        /// Umožní se tak, aby vedlejší graf aktivoval odpovídající řádek, a případně i stránku, na které je obsažen.
        /// </summary>
        [Description("Event vyvolaný po doubleclicku na některém grafu.")]
        [Category("Action")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Browsable(true)]
        public event GridGraphEventHandler GraphRowDoubleClick;
        /// <summary>
        /// Event po změně aktivního řádku
        /// </summary>
        [Description("Event po změně aktivního řádku")]
        [Category("Action")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Browsable(true)]
        public event GridGraphEventHandler RowChangedAfter;
        /// <summary>
        /// Event, který se volá při změně tooltipu (rozsvícení, změna, zhasnutí).
        /// </summary>
        [Browsable(true)]
        [Category("Action")]
        [Description("Event, který se volá při změně tooltipu (rozsvícení, změna, zhasnutí).")]
        public event GridGraphToolTipHandler ToolTipChanged;
        /// <summary>
        /// Event, který bude vyvolán vždy po změně stavu IsUndoEnabled nebo IsRedoEnabled.
        /// Umožní vizuálně reagovat na stav Undo/Redo (enabled na přiměřené buttony).
        /// </summary>
        public event EventHandler EditorStateChanged;
        #endregion
        #region metody
        /// <summary>
        /// Vymaže všechny své řádky a všechna svá další data.
        /// Načte znovu všechny řádky 
        /// </summary>
        public void ReloadRows()
        {
            this.Grid.ReloadRows();
        }
        /// <summary>
        /// Vymaže všechny své řádky a všechna svá další data.
        /// </summary>
        public void ClearRows()
        {
            this.Grid.ClearRows();
        }
        /// <summary>
        /// Metoda, která aktivuje režim Zoom v prostoru grafu.
        /// </summary>
        public void ZoomActivate()
        {
            this.Grid.ZoomActivate();
        }
        /// <summary>
        /// Metoda, která deaktivuje režim Zoom v prostoru grafu.
        /// </summary>
        public void ZoomDeactivate()
        {
            this.Grid.ZoomDeactivate();
        }
        /// <summary>
        /// Tato metoda najednou nastaví Location, Size a InitialTimeRange.
        /// Poznámka: InitialTimeRange se nepředává parametrem, ale je sdíleno prostřednictvím this.TimeAxisCalculator s časovou osou.
        /// Překreslení obsahu tak proběhne jen jedenkrát.
        /// </summary>
        /// <param name="gridArea">Prostor, v němž se má Grid vykreslit</param>
        public void SetBoundsAndTimeRange(Rectangle gridArea)
        {
            this.Grid.SetBoundsAndTimeRange(gridArea);
        }
        /// <summary>
        /// Zaregistruje odkaz na objekt, který je datovým zdrojem tohoto grafického objektu.
        /// </summary>
        /// <param name="dataSource">Objekt, který je datovým zdrojem</param>
        public void RegisterDataSource(IDataSource dataSource)
        {
            this.Grid.RegisterDataSource(dataSource);
        }
        /// <summary>
        /// Zajistí prvotní načtení dat pro určitý datový okruh. Je možno volat kdykoliv. Veškerá předchozí data zahodí (dá Clear).
        /// Další načítání se už nevyvolává programem, ale uživatel si o ně řekne rozbalením prvku, který má subnodes.
        /// </summary>
        /// <param name="firstGId">Specifikace základních dat</param>
        public void ReadFirstDataList(GID firstGId)
        {
            this.Grid.ReadFirstDataList(firstGId);
        }
		/// <summary>
		/// V datovém zdroji došlo ke změně dat, je třeba tuto změnu akceptovat i ve vizuální vrstvě
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="args"></param>
		public void DataSourceDataChanged(object sender, DataSourceEventArgs args)
		{
			this.Grid.DataSourceDataChanged(sender, args);
		}
		#endregion
        #endregion
        #region GRID - EVENTHANLDERY
        private void _RegisterEventsGrid()
        {
			this.Grid.RowFilterChanged += new GridDataRowFilterHandler(Grid_RowFilterChanged);
            this.Grid.StoreTimeAxisData += new TimeAxisSetAxisHandler(Grid_StoreTimeAxisData);
            this.Grid.GraphElementClick += new GridGraphEventHandler(Grid_GraphElementClick);
            this.Grid.GraphRowDoubleClick += new GridGraphEventHandler(Grid_GraphRowDoubleClick);
            this.Grid.RowChangedAfter += new GridGraphEventHandler(Grid_RowChangedAfter);
            this.Grid.ToolTipChanged += new GridGraphToolTipHandler(Grid_ToolTipChanged);
        }
		void Grid_RowFilterChanged(object sender, GridDataRowFilterEventArgs args)
		{
			this.Header.SetRowFilter(args);
		}
        void Grid_StoreTimeAxisData(object sender, TimeAxisSetAxisArgs args)
        {
			if (StoreTimeAxisData != null)
				StoreTimeAxisData(this, args);
			else
				this.Header.SetTimeAxisData(args);
        }
        void Grid_EditorStateChanged(object sender, EventArgs args)
        {
            if (EditorStateChanged != null) EditorStateChanged(this, args);
        }
        void Grid_RequestReloadAllRows(object sender, GridGraphEventArgs args)
        {
            if (RequestReloadAllRows != null) RequestReloadAllRows(this, args);
        }
        void Grid_GraphElementClick(object sender, GridGraphEventArgs args)
        {
            if (GraphElementClick != null) GraphElementClick(this, args);
        }
        void Grid_GraphRowDoubleClick(object sender, GridGraphEventArgs args)
        {
            if (GraphRowDoubleClick != null) GraphRowDoubleClick(this, args);
        }
        void Grid_RowChangedAfter(object sender, GridGraphEventArgs args)
        {
            if (RowChangedAfter != null) RowChangedAfter(this, args);
        }
        void Grid_ToolTipChanged(object sender, GridGraphToolTipEventArgs args)
        {
            if (ToolTipChanged != null) ToolTipChanged(this, args);
        }
        #endregion
        #region SYNCHRONIZER - NAVÁZÁNÍ, METODY PRO SYNCHRONIZACI DAT ODJINUD
        /*
        Objekt této třídy DColGrid z hlediska synchronizeru figuruje jako jednotka.
        Synchronizer se háčkuje na zdejší eventy, například na:
              event TimeAxisChangeHandler IHeaderSync.TimeAxisChange
        Tento event se promítá do standardního eventu (TimeAxisChange).
        Událost (změna času na hlavičce) se přenese z původního objektu (Header) sem (DColGrid), protože je zaháčkovaná:
              this.Header.TimeAxisChange += new TimeAxisChangeHandler(Header_TimeAxisChange);
        Zdejší metoda (void Header_TimeAxisChange) může jednak provést svoji navázanou logiku:
              zavolá metodu this._OnTimeAxisChange(), která zajistí promítnutí změny z hlavičky do Gridu (Grid.Draw()),
        a jednak vyvolá event TimeAxisChange, který si zaregistroval synchronizer (a to tehdy, když se napojoval do this.Synchronizer, viz set accessor).
              iSyncObj.TimeAxisChange += new TimeAxisChangeHandler(_SyncObj_TimeAxisChange);   (v kódu třídy DColumnsSynchronizer._LinkEvents())
        Synchronizer zajistí, že se událost (pokud patří mezi události synchronizované) přenese i do ostatních objektů:
              event Synchronizer._SyncObj_TimeAxisChange   ->  metoda Synchronizer._Sync_TimeAxisRange()  ->  cílový objekt metoda IHeaderSync.SychronizeTimeAxisRangeFrom()
        Touto cestou se tedy cílové objekty dozvědí o události, která vznikla jinde.
        
        Ve zkratce lze tedy popsat cestu události z hlediska tohoto objektu (tedy z pohledu IHeaderSync):
        Událost => handler this.Header_TimeAxisChange => event IHeaderSync.TimeAxisChange => (synchronizer) => přejde do jiného objektu => metoda IHeaderSync.SychronizeTimeAxisRangeFrom(kde source je původce události)
        
        */
        /// <summary>
        /// Objekt Synchronizer, který zajišťuje synchronizaci předepsaných vlastností mezi vícero objekty IHeaderSync.
        /// Synchronizer se vytvoří (jedenkrát jako new DColumnsSynchronizer()), a pak se vloží do všech IHeaderSync, které se mají navzájem synchronizovat.
        /// Při ukončení se do property this.Synchronizer vloží null, tím se DColumns odváže ze synchronizace.
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public DColumnsSynchronizer Synchronizer
        {
            get { return this._Synchronizer; }
            set
            {
                if (value == null)
                {	// Odpojuji se ze synchronizace:
                    if (this._Synchronizer != null)
                        this._Synchronizer.Unlist(this);
                    this._Synchronizer = null;
                }
                else
                {	// Zapojuji se do synchronizace:
                    // Pokud mám referenci na nějaký (starý) synchronizer, tak se z něj nejdřív odpojím:
                    if (this._Synchronizer != null)
                        this._Synchronizer.Unlist(this);

                    // Zapojím se do nově předaného synchronizeru:
                    this._Synchronizer = value;
                    this._Synchronizer.Enlist(this);
                }
            }
        }
        private DColumnsSynchronizer _Synchronizer;

        private void SychronizeColumnHeightFrom(IHeaderSync source, EventArgs args, bool interactive)
        {
            this.Header.SychronizeColumnHeightFrom(source, args, interactive);
            this._ArrangeComponents();
        }
        private void SychronizeColumnWidthFrom(IHeaderSync source, DColumnWidthEventArgs args, bool interactive)
        {
            this.Header.SychronizeColumnWidthFrom(source, args, interactive);
            this._OnColumnsChanged();
        }
        private void SychronizeColumnVisibleFrom(IHeaderSync source, DColumnEventArgs args, bool interactive)
        {
            this.Header.SychronizeColumnVisibleFrom(source, args, interactive);
            this._OnColumnsChanged();
        }
        private void SychronizeColumnOrderFrom(IHeaderSync source, DColumnEventArgs args, bool interactive)
        {
            this.Header.SychronizeColumnOrderFrom(source, args, interactive);
            this._OnColumnsChanged();
        }
        private void SychronizeColumnSortFrom(IHeaderSync source, DColumnEventArgs args, bool interactive)
        {
            this.Header.SychronizeColumnSortFrom(source, args, interactive);
            this._OnColumnsChanged();
        }
        private void SychronizeTimeAxisRangeFrom(IHeaderSync source, TimeAxisChangeEventArgs args, bool interactive)
        {
            this.Header.SychronizeTimeAxisRangeFrom(source, args, interactive);
            this._OnColumnsChanged();
        }
        private void SetTimeAxisData(TimeAxisSetAxisArgs e)
        {
            this.Header.SetTimeAxisData(e);
        }
        private void StopTimeAxisMove()
        {
            this.Header.StopTimeAxisMove();
        }

        #endregion
        #region IHeaderSync Members

        List<TimeAxisTickInfo> IHeaderSync.AxisTicks { get { return this.Header.AxisTicks; } }
        TimeRange IHeaderSync.CurrentTimeRange { get { return this.Header.CurrentTimeRange; } set { this.Header.CurrentTimeRange = value; } }
        ITimeAxisCalc IHeaderSync.TimeAxisCalc { get { return this.Header.TimeAxisCalc; } }
        int IHeaderSync.ColumnHeaderHeightInteractive { get { return this.Header.ColumnHeaderHeightInteractive; } }
        int IHeaderSync.ColumnHeaderHeight { get { return this.Header.ColumnHeaderHeight; } }
        List<DColumn> IHeaderSync.Columns { get { return ((IHeaderSync)this.Header).Columns; } }
        int IHeaderSync.ColumnsCount { get { return this.Header.ColumnsCount; } }

        event EventHandler IHeaderSync.ColumnHeaderHeightChanging
        {
            add { this.ColumnHeaderHeightChanging += value; }
            remove { this.ColumnHeaderHeightChanging -= value; }
        }
        event EventHandler IHeaderSync.ColumnHeaderHeightChanged
        {
            add { this.ColumnHeaderHeightChanged += value; }
            remove { this.ColumnHeaderHeightChanged -= value; }
        }
        event DColumnWidthEventHandler IHeaderSync.ColumnWidthChanging
        {
            add { this.ColumnWidthChanging += value; }
            remove { this.ColumnWidthChanging -= value; }
        }
        event DColumnWidthEventHandler IHeaderSync.ColumnWidthChanged
        {
            add { this.ColumnWidthChanged += value; }
            remove { this.ColumnWidthChanged -= value; }
        }
        event DColumnEventHandler IHeaderSync.ColumnVisibleChanged
        {
            add { this.ColumnVisibleChanged += value; }
            remove { this.ColumnVisibleChanged -= value; }
        }
        event TimeAxisChangeHandler IHeaderSync.TimeAxisChange
        {
            add { this.TimeAxisChange += value; }
            remove { this.TimeAxisChange -= value; }
        }
        event DColumnEventHandler IHeaderSync.ColumnSortChanged
        {
            add { this.ColumnSortChanged += value; }
            remove { this.ColumnSortChanged -= value; }
        }
        event DColumnRowFilterEventHandler IHeaderSync.RowFilterChanged
        {
            add { this.RowFilterChanged += value; }
            remove { this.RowFilterChanged -= value; }
        }

        void IHeaderSync.SychronizeColumnHeightFrom(IHeaderSync source, EventArgs args, bool interactive)
        {
            this.SychronizeColumnHeightFrom(source, args, interactive);
        }
        void IHeaderSync.SychronizeColumnWidthFrom(IHeaderSync source, DColumnWidthEventArgs args, bool interactive)
        {
            this.SychronizeColumnWidthFrom(source, args, interactive);
        }
        void IHeaderSync.SychronizeColumnVisibleFrom(IHeaderSync source, DColumnEventArgs args, bool interactive)
        {
            this.SychronizeColumnVisibleFrom(source, args, interactive);
        }
        void IHeaderSync.SychronizeColumnOrderFrom(IHeaderSync source, DColumnEventArgs args, bool interactive)
        {
            this.SychronizeColumnOrderFrom(source, args, interactive);
        }
        void IHeaderSync.SychronizeColumnSortFrom(IHeaderSync source, DColumnEventArgs args, bool interactive)
        {
            this.SychronizeColumnSortFrom(source, args, interactive);
        }
        void IHeaderSync.SychronizeTimeAxisRangeFrom(IHeaderSync source, TimeAxisChangeEventArgs args, bool interactive)
        {
            this.SychronizeTimeAxisRangeFrom(source, args, interactive);
        }

        void IHeaderSync.SuppressDrawingPush() { this.SuppressDrawingPush(); }
        void IHeaderSync.SuppressDrawingPop() { this.SuppressDrawingPop(); }
        bool IHeaderSync.SuppressDrawing { get { return this.SuppressDrawing; } set { this.SuppressDrawing = value; } }
        void IHeaderSync.SetTimeAxisData(TimeAxisSetAxisArgs e) { this.SetTimeAxisData(e); }
        void IHeaderSync.StopTimeAxisMove() { this.StopTimeAxisMove(); }

        #endregion
        #region IGraphPointer : pointer na místo v grafu
        /// <summary>
        /// Metoda akceptuje (převezme do vizuální vrstvy) data z daného pointeru
        /// </summary>
        /// <param name="graphPointer"></param>
        public void GraphPointerAccept(IGraphPointer graphPointer)
        {
			Steward.ExecuteInTryCatch(delegate
			{
				this.Header.TimeAxis.AxisVisibleTimeRange = graphPointer.Time;    // Header: TimeRange  (je možno i touto formou: this.Header.SetTimeAxisData(new TimeAxisSetAxisArgs(graphPointer.Time));   )
				this.Grid.GraphPointerAccept(graphPointer);                       // Graph : nodes, first row & pixel
				// this.Header.RowFilter = graphPointer.RowFilter;     RowFilter nelze vložit teď. Nejprve se musí načíst (asynchronně) data do řádků. Více viz this.Grid.GraphPointerAccept().
			}, "Zvolenou položku není možno najít.");
        }
        /// <summary>
        /// Metoda naplní (z vizuální vrstvy do dodaného objektu) informace pro uložení pointeru.
        /// </summary>
        /// <param name="graphPointer"></param>
        public void GraphPointerFill(IGraphPointer graphPointer)
        {
			Steward.ExecuteInTryCatch(delegate
			{
				graphPointer.Time = this.Header.TimeAxis.AxisVisibleTimeRange;    // Header: TimeRange
				this.Grid.GraphPointerFill(graphPointer);                         // Graph : nodes, first row & pixel
				graphPointer.RowFilter = (this.Header.ContainRowFilter ? this.Header.RowFilter : null);
			}, "Zvolenou položku není možno vytvořit.");
		}
        #endregion
        #region LAYOUT
        /// <summary>
		/// Aktuální layout.
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		internal DHeaderGridLayout GridLayout { get { return this.Header.GridLayout; } }
		/// <summary>
		/// Načte z registru layout a promítne jej do this, pomocí virtuální metody this.LayoutImportFrom().
		/// Na závěr volá event ColumnWidthChanged.
		/// </summary>
		/// <param name="layoutName"></param>
		internal void LayoutLoad(string layoutName)
		{
			this.LayoutLoad(layoutName, false);
		}
		/// <summary>
		/// Načte z registru layout a promítne jej do this, pomocí virtuální metody this.LayoutImportFrom().
		/// Na závěr volá event ColumnWidthChanged.
		/// </summary>
		/// <param name="layoutName"></param>
		/// <param name="withForm">Načíst i pozici a rozměry formuláře</param>
		internal void LayoutLoad(string layoutName, bool withForm)
		{
			this.Header.LayoutLoad(layoutName, withForm);
			this.Grid.AcceptColumnDimensions();
		}
		/// <summary>
		/// Uloží aktuální layout do registru.
		/// </summary>
		internal void LayoutSave()
		{
			LayoutSave(false);
		}
		/// <summary>
		/// Uloží aktuální layout do registru.
		/// </summary>
		/// <param name="withForm">Uložit i pozici a rozměry formuláře</param>
		internal void LayoutSave(bool withForm)
		{
			this.Header.LayoutSave(withForm);
		}
        /// <summary>
        /// Metoda zajistí převzetí uspořádání záhlaví a šířky všech sloupců z dodaného objektu.
        /// Slouží k hromadnému načtení dat. Nevyvolává žádné eventy ani Draw().
        /// Příští Draw() překreslí obsah.
        /// Odpovídající reciproční metoda je LayoutExportTo().
        /// </summary>
        /// <param name="widthList"></param>
        internal virtual void LayoutImportFrom(IGraphLayout graphLayout, bool interactive)
        {
            this.Header.LayoutImportFrom(graphLayout, interactive);
        }
        /// <summary>
        /// Metoda zajistí to, že aktuální dimenze v controlu se uloží do dodaného objektu Layout.
        /// </summary>
        /// <param name="graphLayout"></param>
        internal virtual void LayoutExportTo(IGraphLayout graphLayout)
        {
            this.Header.LayoutExportTo(graphLayout);
        }
        #endregion
    }
}
